using System;
using System.Diagnostics;
using System.IO;

namespace Pegasus.Diagnostics.Telnet
{
	/// <summary>
	/// Implements the Listen command for the telnet service
	/// </summary>
	public class CommandListen : ITelnetCommand
	{
		// Local Instanc Values

		// Listener value must be thread safe so us locks when accessing this value.
		private TextWriterTraceListener m_listener = null;

		/// <summary>
		/// Default Constructor
		/// </summary>
		public CommandListen()
		{
		}

		/// <summary>
		/// The names of the command that the user types in.
		/// </summary>
		public string Command
		{
			get
			{
				return "listen";
			}
		}

		/// <summary>
		/// Any short cut commands or key (i.e. quit uses q and exit)
		/// </summary>
		public string[] CommandShortCuts
		{
			get
			{
				return new string[] { "l" };
			}
		}

		/// <summary>
		/// Execute the command.
		/// </summary>
		/// <param name="args">Additional parameters that the user typed in.</param>
		/// <param name="writer">Text stream to write to</param>
		public void ExecCommand( TextWriter writer, string[] args )
		{
			if( args.Length > 0 )
			{
				if( args[ 0 ].ToLower() == "on" )
				{
					TurnOnListener( writer );
				}
				else if( args[ 0 ].ToLower() == "off" )
				{
					TurnOffListener();
				}
				if( args[ 0 ].ToLower() == "alloff" )
				{
					// This is a hidden option to get out of a state we we have a listener
					// connected to an orphened socket.  Not sure how we get in this state.
					// TODO: Fix the listerner problem.
					TurnOnListener( writer );
					Trace.Listeners.Clear();
				}
			}

			string onOff = string.Empty;

			lock( this )
			{
				onOff = ( m_listener == null ? "off" : "on" );
			}

			writer.WriteLine( "Session trace listener " + onOff );
		}

		/// <summary>
		/// Show a single line of help about the command
		/// </summary>
		/// <returns>Single line brief description of command</returns>
		public string GetHelp()
		{
			return "Turn on or off trace listening for this telnet session.";
		}

		/// <summary>
		/// Show a the full usage help about the command
		/// </summary>
		/// <param name="writer">Text stream to write to</param>
		public void ShowDetailedHelp( TextWriter writer )
		{
			writer.WriteLine( "Command: listen | l" );
			writer.WriteLine( "Usage: listen [ on | off ]" );
			writer.WriteLine();
			writer.WriteLine( "Description:  Turn on or off trace listening for this telnet session." );
		}

		/// <summary>
		/// Stop the listener
		/// </summary>
		public void Stop()
		{
			TurnOffListener();
		}

		/// <summary>
		/// Turn the trace listener on
		/// </summary>
		/// <param name="writer">Text stream to write to</param>
 		private void TurnOnListener( TextWriter writer )
		{
			lock( this )
			{
				if( m_listener == null )
				{
					m_listener = new TextWriterTraceListener( writer );

					Trace.AutoFlush = true;
					Trace.Listeners.Add( m_listener );
				}
			}
		}

		/// <summary>
		/// Turn the trace listener off
		/// </summary>
		private void TurnOffListener()
		{
			lock( this )
			{
				if( m_listener != null )
				{
					Trace.Listeners.Remove( m_listener );
					m_listener = null;
				}
			}
		}
	}
}
